#include "tcp.hpp"
#include "Protocol.hpp"
#include "pthread_pool.hpp"
#include <wait.h>
using namespace MY_TCP;
void fork_son(int port)
{
  // signal忽略 ||  子进程再创建子进程，退出子进程，将孙子进程交给OS
  signal(SIGCHLD, SIG_IGN);
  int sock_fd = TCP_SOCK::Sock();
  TCP_SOCK::Bind(sock_fd, port);
  bool quit = false;
  if (TCP_SOCK::Listen(sock_fd) < 0)
  {
    std::cerr << "not client" << std::endl;
    exit(2);
  }
  while (!quit)
  {
    int waiter_fd = TCP_SOCK::Accept(sock_fd);
    if (waiter_fd < 0)
    {
      std::cerr << "accept error" << std::endl;
      continue;
    }
    if (fork() == 0)
    {
      // 业务处理
      std::cout << "client connect server use " << waiter_fd << " " << getpid() << std::endl;
      char str[1024];
      recv(waiter_fd, (void *)str, sizeof(str), 0);
      request_t req;
      DeserializeRequest(str, req);
      response_t res;
      res.run(req.x, req.y, req.op);
      std::string res_string = SerializeResponse(res);
      send(waiter_fd, res_string.c_str(), res_string.size(), 0);
      close(waiter_fd);
      exit(0);
    }
    else
    {
      close(waiter_fd);
    }
  }
}
void fork_grandson(int port)
{
  int sock_fd = TCP_SOCK::Sock();
  TCP_SOCK::Bind(sock_fd, port);
  if (TCP_SOCK::Listen(sock_fd) < 0)
  {
    std::cerr << "not client" << std::endl;
    exit(2);
  }
  bool quit = false;
  while (!quit)
  {
    int new_fd = TCP_SOCK::Accept(sock_fd);
    if (new_fd < 0)
    {
      std::cerr << "new link is error" << std::endl;
      continue;
    }
    std::cout << "get new link" << std::endl;
    int son_fd = fork();
    if (son_fd < 0)
    {
      close(new_fd);
      std::cerr << "new fork is error" << std::endl;
      continue;
    }
    else if (son_fd == 0)
    {
      if (fork() == 0)
      {
        std::cout << "get new link" << std::endl;
        // 处理业务
        char buf[1024];
        // 接收
        recv(new_fd, (void *)buf, sizeof(buf), 0);
        // 反序列化
        request_t req;
        DeserializeRequest(buf, req);
        response_t res;
        res.run(req.x, req.y, req.op);
        // 序列化
        std::string str = SerializeResponse(res);
        // 回复
        send(new_fd, str.c_str(), str.size(), 0);
        close(new_fd);
        exit(0);
      }
      close(new_fd);
      exit(0);
    }
    else
    {
      close(new_fd);
      waitpid(son_fd, nullptr, 0);
    }
  }
}
void fork_text(int port)
{
  // fork_son(port);
  fork_grandson(port);
}
static pthread_mutex_t take = PTHREAD_MUTEX_INITIALIZER;
void *Doing(void *argv)
{
  pthread_detach(pthread_self());
  int sock_fd = *(int *)argv;
  bool quit = false;
  while (!quit)
  {
    pthread_mutex_lock(&take);
    int new_fd = TCP_SOCK::Accept(sock_fd);
    pthread_mutex_unlock(&take);

    std::cout << "get new link"
              << "  new_fd:" << new_fd << std::endl;
    // 处理业务
    char buf[1024];
    // 接收
    recv(new_fd, (void *)buf, sizeof(buf), 0);
    // 反序列化
    request_t req;
    DeserializeRequest(buf, req);
    response_t res;
    res.run(req.x, req.y, req.op);
    // 序列化
    std::string str = SerializeResponse(res);
    // 回复
    send(new_fd, str.c_str(), str.size(), 0);
    close(new_fd);
  }
}
void pthread_text(int port)
{
  int sock_fd = TCP_SOCK::Sock();
  TCP_SOCK::Bind(sock_fd, port);
  TCP_SOCK::Listen(sock_fd);
  pthread_t waiter[5];
  for (int i = 0; i < 5; i++)
  {
    pthread_create(waiter + i, nullptr, Doing, (void *)&sock_fd);
  }
  while (true)
    ;
}
void pthread_pool_text(int port)
{
  int sock_fd = TCP_SOCK::Sock();
  TCP_SOCK::Bind(sock_fd, port);
  TCP_SOCK::Listen(sock_fd);

  // Pthread_Pool<response_t*>* it = Pthread_Pool<response_t*>::InitPthreadPool();
  auto it = Pthread_Pool<response_t*>::InitPthreadPool();

  bool quit = false;
  while (!quit)
  {
    int new_fd = TCP_SOCK::Accept(sock_fd);
    if (new_fd < 0)
    {
      continue;
    }
    std::cout << "get new link"
              << "  new_fd:" << new_fd << std::endl;
    // 开始业务处理
    char buf[1024];
    // 接收
    recv(new_fd, (void *)buf, sizeof(buf), 0);
    // 反序列化
    request_t req;
    DeserializeRequest(buf, req);
    response_t* res = new response_t(req.x, req.y, req.op);
    it->GetWork(res);
    usleep(1);
    // 序列化
    std::string str = SerializeResponse(*res);
    delete res;
    // 回复
    send(new_fd, str.c_str(), str.size(), 0);
    close(new_fd);
  }
}
void Usage(std::string command)
{
  std::cout << command << " port" << std::endl;
}   
int main(int args, char *argv[])
{
  if (args != 2)
  {
    std::cerr << "use error" << std::endl;
    Usage(argv[0]);
    exit(1);
  }
  int port = atoi(argv[1]);
  //          //1.子进程版
  // fork_text(port);
  //          //2.多线程版
  // pthread_text(port);
  //          //3.线程池版
  pthread_pool_text(port);
  return 0;
}
